<?php

namespace Coldwind;

/**
 * 插件定义类
 * 借鉴了OneThink相关代码
 * @author ZXZ <zxz054321@163.com>
 */
abstract class Addon {

    private static $_systemHooks = array(
        array('name' => 'app_init', 'description' => '系统：应用初始化标签位'),
        array('name' => 'path_info', 'description' => '系统：PATH_INFO检测标签位'),
        array('name' => 'app_begin', 'description' => '系统：应用开始标签位'),
        array('name' => 'action_name', 'description' => '系统：操作方法名标签位'),
        array('name' => 'action_begin', 'description' => '系统：控制器开始标签位'),
        array('name' => 'view_begin', 'description' => '系统：视图输出开始标签位'),
        array('name' => 'view_parse', 'description' => '系统：视图解析标签位'),
        array('name' => 'template_filter', 'description' => '系统：模板内容解析标签位'),
        array('name' => 'view_filter', 'description' => '系统：视图输出过滤标签位'),
        array('name' => 'view_end', 'description' => '系统：视图输出结束标签位'),
        array('name' => 'action_end', 'description' => '系统：控制器结束标签位'),
        array('name' => 'app_end', 'description' => '系统：应用结束标签位'),
    );

    /**
     * $info = array(
     *  'name'=>'AddonName',
     *  'title'=>'名称',
     *  'description'=>'插件描述',
     *  'author'=>'ZXZ',
     *  'version'=>'0.1',
     *  'status'=>1,//默认是否启用
     *  );
     */
    public $info = array();

    public function __construct() {
        //TODO: 多插件同时运行是否导致定义失效
        define('ADDON_NAME', $this->getName());
    }

    final public function getName() {
        $class = get_class($this);
        return substr($class, strrpos($class, '\\') + 1, -5);
    }

    final static public function getSystemHooks() {
        return static::$_systemHooks;
    }

    final public function checkInfo() {
        $keys = array('name', 'title', 'description', 'author', 'version', 'status');
        foreach ($keys as $value) {
            if (!array_key_exists($value, $this->info))
                return FALSE;
        }
        return TRUE;
    }

    //必须实现安装
    abstract public function install();

    //必须卸载插件方法
    abstract public function uninstall();

    /**
     * 仅用于插件安装时 注册插件自身的钩子（系统未内置）
     * @param type $name
     * @param type $description
     * @return boolean
     */
    final protected function registerHook($name, $description = '') {
        $count = M('Hooks')->where(array('name' => $name))->count();
        if ($count > 0)
            return TRUE;

        return M('Hooks')->add(array(
                    'name' => $name,
                    'description' => $description
        ));
    }

    /**
     * 仅用于插件卸载时 删除插件自身的钩子（系统未内置）
     * @param type $name
     * @return boolean
     */
    final protected function unregisterHook($name) {
        //系统钩子不可删除
        foreach (static::$_systemHooks as $hookArr) {
            if ($name == $hookArr['name'])
                return TRUE;
        }

        //TODO:钩子上没任何插件挂载才可删除
        $num = D('ListenView')
                ->where(array('hook_name' => $name))
                ->count();
        dump(D('ListenView')
                        ->where(array('hook_name' => $name))->select());
        E('TODO');
        M('Hooks')->where(array('name' => $name));
//        if ($num > 1) {
//            
//        } else {
//            return M('Hooks')->delete();
//        }
        S('hooks', null);
    }

    /**
     * 调用插件模型
     * @param type $name
     * @return type
     */
    final protected function model($name) {
        return D('Addons://' . $this->getName() . '/' . $name);
    }

    /**
     * 执行SQL文件（用于安装卸载）
     * @param string $name 文件名（不带后缀.sql）
     */
    protected function excuteSqlFile($name) {
        $file = APP_PATH . 'Addons/' . $this->getName() . '/' . $name . '.sql';
        excute_sql_file($file);

        if (C('AUTO_DELETE_SQL_FILE') === TRUE)
            unlink($file);
    }

}
